/*
 *  tracker/SectionSamples.cpp
 *
 *  Copyright 2009 Peter Barth
 *
 *  This file is part of Milkytracker.
 *
 *  Milkytracker is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  Milkytracker is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with Milkytracker.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

/*
 *  SectionSamples.cpp
 *  MilkyTracker
 *
 *  Created by Peter Barth on 15.04.05.
 *
 */

#include "SectionSamples.h"

#include "PPUI.h"
#include "TransparentContainer.h"
#include "Tracker.h"
#include "TrackerConfig.h"
#include "ModuleEditor.h"
#include "SamplePlayer.h"
#include "PatternEditorControl.h"
#include "SampleEditorControl.h"
#include "SectionInstruments.h"
#include "DialogBase.h"

// OS Interface
#include "PPOpenPanel.h"
#include "PPSavePanel.h"

#include "ControlIDs.h"

enum ControlIDs
{
    STATICTEXT_DISPLAY = 0xF000,
    STATICTEXT_LENGTH,
    STATICTEXT_REPSTART,
    STATICTEXT_REPLEN,
    BUTTON_SHOWRANGE,
    BUTTON_FLIPNUMBERFORMAT,
    // Only low-res
    CONTAINER_SHOWCONTEXTMENU,
    BUTTON_SHOWCONTEXTMENU
};

// Class which responds to message box clicks
class DialogResponderSamples : public DialogResponder
{
    private:
        SectionSamples& section;
    public:
        DialogResponderSamples (SectionSamples& section) :
            section(section)
        {
        }

        virtual pp_int32 ActionOkay(PPObject* sender)
        {
            switch (reinterpret_cast<PPDialogBase*>(sender)->getID())
            {
                case MESSAGEBOX_CLEARSAMPLE:
                    section.getSampleEditorControl()->getSampleEditor()->clearSample();
                    break;

                case MESSAGEBOX_CROPSAMPLE:
                    section.getSampleEditorControl()->getSampleEditor()->cropSample();
                    break;

                case MESSAGEBOX_MINIMIZESAMPLE:
                    section.getSampleEditorControl()->getSampleEditor()->minimizeSample();
                    break;

                case MESSAGEBOX_CONVERTSAMPLE:
                    section.getSampleEditorControl()->getSampleEditor()->convertSampleResolution(true);
                    section.getSampleEditorControl()->showAll();
                    break;
            }
            return 0;
        }

        virtual pp_int32 ActionNo(PPObject* sender)
        {
            switch (reinterpret_cast<PPDialogBase*>(sender)->getID())
            {
                case MESSAGEBOX_CONVERTSAMPLE:
                    section.getSampleEditorControl()->getSampleEditor()->convertSampleResolution(false);
                    section.getSampleEditorControl()->showAll();
                    break;
            }
            return 0;
        }
};

SectionSamples::SectionSamples (Tracker& theTracker) :
    SectionAbstract(theTracker, NULL, new DialogResponderSamples(*this)),
    containerEntire(NULL),
    visible(false),
    sampleEditorControl(NULL),
    currentSamplePlayNote(ModuleEditor::MAX_NOTE / 2),
    showRangeOffsets(false),
    offsetFormat(0)
{
}

SectionSamples::~SectionSamples ()
{
}

pp_int32 SectionSamples::handleEvent(PPObject* sender, PPEvent* event)
{
    PPScreen* screen = tracker.screen;
    ModuleEditor* moduleEditor = tracker.moduleEditor;
    SampleEditor* sampleEditor = sampleEditorControl->getSampleEditor();

    if (event->getID() == eUpdateChanged)
    {
        tracker.updateWindowTitle();
    }
    else if (event->getID() == eCommand || event->getID() == eCommandRepeat)
    {
        switch (reinterpret_cast<PPControl*>(sender)->getID())
        {
            // sample editor

            // load sample
            case BUTTON_SAMPLE_LOAD:
            {
                if (event->getID() != eCommand)
                    break;

                tracker.loadType(FileTypes::FileTypeSongAllSamples);
                break;
            }

            // save sample
            case BUTTON_SAMPLE_SAVE:
            {
                if (event->getID() != eCommand)
                    break;

                if (isEmptySample())
                    tracker.showMessageBox(MESSAGEBOX_UNIVERSAL, "Sample is empty.", Tracker::MessageBox_OK);
                else
                    tracker.saveType(tracker.getCurrentSelectedSampleSaveType());
                break;
            }

            case BUTTON_SAMPLE_PLAY_UP:
                if (currentSamplePlayNote < 95)
                    currentSamplePlayNote++;
                refresh();
                break;

            case BUTTON_SAMPLE_PLAY_DOWN:
                if (currentSamplePlayNote > 0)
                    currentSamplePlayNote--;
                refresh();
                break;

            case BUTTON_SAMPLE_PLAY_WAVE:
            {
                SamplePlayer samplePlayer(*moduleEditor, *tracker.playerController);
                samplePlayer.playCurrentSample(currentSamplePlayNote);
                break;
            }

            case BUTTON_SAMPLE_PLAY_RANGE:
            {
                SamplePlayer samplePlayer(*moduleEditor, *tracker.playerController);
                samplePlayer.playCurrentSampleSelectionRange(currentSamplePlayNote);
                break;
            }

            case BUTTON_SAMPLE_PLAY_DISPLAY:
            {
                SamplePlayer samplePlayer(*moduleEditor, *tracker.playerController);
                samplePlayer.playSample(*sampleEditor->getSample(),
                                        currentSamplePlayNote,
                                        sampleEditorControl->getCurrentPosition(),
                                        sampleEditorControl->getCurrentPosition() + sampleEditorControl->getCurrentDisplayRange());
                break;
            }

            case BUTTON_SAMPLE_PLAY_STOP:
            {
                SamplePlayer samplePlayer(*moduleEditor, *tracker.playerController);
                samplePlayer.stopSamplePlayback();
                break;
            }

            case BUTTON_SAMPLE_RANGE_SHOW:
                if (event->getID() != eCommand)
                    break;

                sampleEditorControl->showRange();
                refresh();
                break;

            case BUTTON_SAMPLE_RANGE_ALL:
                if (event->getID() != eCommand)
                    break;

                sampleEditorControl->rangeAll(true);
                break;

            case BUTTON_SAMPLE_RANGE_CLEAR:
                sampleEditorControl->rangeClear(true);
                break;

            case BUTTON_SAMPLE_RANGE_ZOOMOUT:
                if (event->getID() != eCommand)
                    break;

                sampleEditorControl->zoomOut();
                refresh();
                break;

            case BUTTON_SAMPLE_RANGE_SHOWALL:
                if (event->getID() != eCommand)
                    break;

                sampleEditorControl->showAll();
                refresh();
                break;

            case BUTTON_SAMPLE_APPLY_LASTFILTER:
                if (event->getID() != eCommand)
                    break;

                sampleEditor->tool_applyLastFilter();
                break;

            case BUTTON_SAMPLE_UNDO:
                if (event->getID() != eCommand)
                    break;

                sampleEditor->undo();
                break;

            case BUTTON_SAMPLE_REDO:
                if (event->getID() != eCommand)
                    break;

                sampleEditor->redo();
                break;

            case BUTTON_SAMPLE_EDIT_CUT:
                if (event->getID() != eCommand)
                    break;

                sampleEditor->cut();
                break;

            case BUTTON_SAMPLE_EDIT_COPY:
                if (event->getID() != eCommand)
                    break;

                sampleEditor->copy();
                break;

            case BUTTON_SAMPLE_EDIT_PASTE:
                if (event->getID() != eCommand)
                    break;

                sampleEditor->paste();
                break;

            case BUTTON_SAMPLE_EDIT_REPSTARTPLUS:
                if (showRangeOffsets)
                {
                    sampleEditorControl->increaseRangeStart();
                    refresh();
                }
                else
                    sampleEditor->increaseRepeatStart();
                break;

            case BUTTON_SAMPLE_EDIT_REPSTARTMINUS:
                if (showRangeOffsets)
                {
                    sampleEditorControl->decreaseRangeStart();
                    refresh();
                }
                else
                    sampleEditor->decreaseRepeatStart();
                break;

            case BUTTON_SAMPLE_EDIT_REPLENPLUS:
                if (showRangeOffsets)
                {
                    sampleEditorControl->increaseRangeEnd();
                    refresh();
                }
                else
                    sampleEditor->increaseRepeatLength();
                break;

            case BUTTON_SAMPLE_EDIT_REPLENMINUS:
                if (showRangeOffsets)
                {
                    sampleEditorControl->decreaseRangeEnd();
                    refresh();
                }
                else
                    sampleEditor->decreaseRepeatLength();
                break;

            case BUTTON_SAMPLE_EDIT_CLEAR:
            {
                if (event->getID() != eCommand)
                    break;

                handleClearSample();
                break;
            }

            case BUTTON_SAMPLE_EDIT_MINIMIZE:
            {
                if (event->getID() != eCommand)
                    break;

                handleMinimizeSample();
                break;
            }

            case BUTTON_SAMPLE_EDIT_CROP:
            {
                if (event->getID() != eCommand)
                    break;

                handleCropSample();
                break;
            }

            case BUTTON_SAMPLE_EDIT_VOL:
            {
                if (event->getID() != eCommand)
                    break;

                getSampleEditorControl()->invokeSetSampleVolume();
                break;
            }

            case BUTTON_SAMPLE_EDIT_DRAW:
            {
                if (event->getID() != eCommand)
                    break;

                getSampleEditorControl()->setDrawMode(!getSampleEditorControl()->getDrawMode());
                PPButton* button = reinterpret_cast<PPButton*>(sender);
                button->setPressed(getSampleEditorControl()->getDrawMode());
                screen->paintControl(button);
                break;
            }

            case BUTTON_SAMPLE_ZOOM_PLUS:
                getSampleEditorControl()->scrollWheelZoomIn();
                break;

            case BUTTON_SAMPLE_ZOOM_MINUS:
                getSampleEditorControl()->scrollWheelZoomOut();
                break;


            case STATICTEXT_REPSTART:
            case STATICTEXT_REPLEN:
            case STATICTEXT_SAMPLE_REPSTART:
            case STATICTEXT_SAMPLE_REPLENGTH:
            case BUTTON_SHOWRANGE:
                if (event->getID() != eCommand)
                    break;

                showRangeOffsets = !showRangeOffsets;
                refresh();
                break;

            case BUTTON_FLIPNUMBERFORMAT:
                if (event->getID() != eCommand)
                    break;

                toggleOffsetFormat();
                refresh();
                break;

            case BUTTON_SHOWCONTEXTMENU:
                if (event->getID() != eCommand)
                    break;

                getSampleEditorControl()->invokeContextMenu(reinterpret_cast<PPControl*>(sender)->getLocation(), false);
                break;

        }
    }
    else if (event->getID() == eSelection)
    {

        switch (reinterpret_cast<PPControl*>(sender)->getID())
        {
            case RADIOGROUP_SAMPLE_RESTYPE:
            {
                handleConvertSampleResolution();
                break;
            }

            case RADIOGROUP_SAMPLE_LOOPTYPE:
            {
                sampleEditor->setLoopType((mp_ubyte)((reinterpret_cast<PPRadioGroup*>(sender)->getChoice()) & 3));
                refresh();
                break;
            }
        }

    }
    else if (event->getID() == eUpdated)
    {
        switch (reinterpret_cast<PPControl*>(sender)->getID())
        {
            case SAMPLE_EDITOR:
            {
                // redraw sample editor
                realUpdate(true, true, false);
                break;
            }
        }
    }

    return 0;
}

void SectionSamples::init()
{
    init(0, tracker.MAXEDITORHEIGHT() - tracker.SAMPLESECTIONDEFAULTHEIGHT());
}

void SectionSamples::init(pp_int32 x, pp_int32 y)
{
    PPScreen* screen = tracker.screen;

    containerEntire = new PPTransparentContainer(CONTAINER_ENTIRESMPSECTION, screen, this,
                                                 PPPoint(0, 0), PPSize(screen->getWidth(), screen->getHeight()));

    #ifndef __LOWRES__
    pp_int32 conSize1 = (pp_int32)(screen->getWidth() * 0.1359375f);
    pp_int32 conSize2 = (pp_int32)(screen->getWidth() * 0.215625f);
    pp_int32 conSize3 = (pp_int32)(screen->getWidth() * 0.0734375f);
    pp_int32 conSize4 = (pp_int32)(screen->getWidth() * 0.075f);
    pp_int32 conSize5 = (pp_int32)(screen->getWidth() * 0.128125f);
    pp_int32 conSize6 = (pp_int32)(screen->getWidth() * 0.103125f);
    pp_int32 conSize7 = (pp_int32)(screen->getWidth() * 0.2525f);

    pp_int32 dHeight = 12 * 4 + 8;
    pp_int32 bHeight = (dHeight - 4) / 3;
    pp_int32 bHeightm = bHeight - 1;

    pp_int32 cHeight = tracker.SAMPLESECTIONDEFAULTHEIGHT() - dHeight - 1;

    // sample editor
    PPContainer* sampleEditorContainer = new PPContainer(CONTAINER_SAMPLEEDITOR, screen, this, PPPoint(x, y), PPSize(screen->getWidth(), cHeight), false);
    sampleEditorContainer->setColor(TrackerConfig::colorThemeMain);

    sampleEditorControl = new SampleEditorControl(SAMPLE_EDITOR, screen, this, PPPoint(x + 2, y + 2), PPSize(sampleEditorContainer->getSize().width - 4, sampleEditorContainer->getSize().height - 4));
    sampleEditorControl->attachSampleEditor(tracker.moduleEditor->getSampleEditor());
    sampleEditorControl->setBorderColor(TrackerConfig::colorThemeMain);

    sampleEditorContainer->addControl(sampleEditorControl);

    containerEntire->addControl(sampleEditorContainer);

    pp_int32 x2 = x;
    pp_int32 y2 = sampleEditorContainer->getSize().height + y;

    PPContainer* container = new PPContainer(CONTAINER_SAMPLE_PLAY, screen, this, PPPoint(x2, y2), PPSize(conSize1, dHeight), false);
    container->setColor(TrackerConfig::colorThemeMain);

    container->addControl(new PPStaticText(0, NULL, NULL, PPPoint(x2 + 4, y2 + 2), "Play:", true));
    container->addControl(new PPStaticText(STATICTEXT_SAMPLE_PLAYNOTE, screen, this, PPPoint(x2 + 8, y2 + 2 + bHeight + 2), "C-5", false));

    pp_int32 size = (pp_int32)(conSize1 * 0.2183908045977f);
    pp_int32 size2 = (pp_int32)(conSize1 * 0.4367816091954f);
    pp_int32 size3 = (pp_int32)(conSize1 /*0.2988505747126f*/ * 0.3218390804598f);

    PPButton* button = new PPButton(BUTTON_SAMPLE_PLAY_UP, screen, this, PPPoint(x2 + size2, y2 + 2 + bHeight), PPSize(size, bHeightm));
    button->setText("Up");
    container->addControl(button);

    button = new PPButton(BUTTON_SAMPLE_PLAY_DOWN, screen, this, PPPoint(x2 + size2, y2 + 2 + bHeight * 2), PPSize(size, bHeightm + 1));
    button->setText("Dn");
    container->addControl(button);

    button = new PPButton(BUTTON_SAMPLE_PLAY_STOP, screen, this, PPPoint(x2 + 2, y2 + 2 + bHeight * 2), PPSize(size2 - 3, bHeightm + 1));
    button->setText("Stop");
    container->addControl(button);

    button = new PPButton(BUTTON_SAMPLE_PLAY_WAVE, screen, this, PPPoint(x2 + 2 + size + size2 - 1, y2 + 2), PPSize(size3, bHeightm));
    button->setText("Wav");
    container->addControl(button);

    button = new PPButton(BUTTON_SAMPLE_PLAY_RANGE, screen, this, PPPoint(x2 + 2 + size + size2 - 1, y2 + 2 + bHeight), PPSize(size3, bHeightm));
    button->setText("Rng");
    container->addControl(button);

    button = new PPButton(BUTTON_SAMPLE_PLAY_DISPLAY, screen, this, PPPoint(x2 + 2 + size + size2 - 1, y2 + 2 + bHeight * 2), PPSize(size3, bHeightm + 1));
    button->setText("Dsp");
    container->addControl(button);

    containerEntire->addControl(container);

    size = (conSize2 - 4) / 2 - 1;

    x2 += container->getSize().width;
    container = new PPContainer(CONTAINER_SAMPLE_RANGE, screen, this, PPPoint(x2, y2), PPSize(conSize2, dHeight), false);
    container->setColor(TrackerConfig::colorThemeMain);

    button = new PPButton(BUTTON_SAMPLE_RANGE_SHOW, screen, this, PPPoint(x2 + 2, y2 + 2), PPSize(size, bHeightm));
    button->setText("Show rng");
    container->addControl(button);

    button = new PPButton(BUTTON_SAMPLE_RANGE_ALL, screen, this, PPPoint(x2 + 2, y2 + 2 + bHeight), PPSize(size, bHeightm));
    button->setText("Rng all");
    container->addControl(button);

    pp_int32 h = button->getSize().width;

    button = new PPButton(BUTTON_SAMPLE_UNDO, screen, this, PPPoint(x2 + 2, y2 + 2 + bHeight * 2), PPSize((size >> 1), bHeightm + 1));
    button->setText("Undo");
    container->addControl(button);

    button = new PPButton(BUTTON_SAMPLE_REDO, screen, this, PPPoint(x2 + 2 + (size >> 1) + 1, y2 + 2 + bHeight * 2), PPSize(h - (size >> 1) - 1, bHeightm + 1));
    button->setText("Redo");
    container->addControl(button);

    button = new PPButton(BUTTON_SAMPLE_RANGE_ZOOMOUT, screen, this, PPPoint(x2 + 2 + size + 1, y2 + 2), PPSize(size, bHeightm));
    button->setText("Zoom out");
    container->addControl(button);

    button = new PPButton(BUTTON_SAMPLE_RANGE_SHOWALL, screen, this, PPPoint(x2 + 2 + size + 1, y2 + 2 + bHeight), PPSize(size, bHeightm));
    button->setText("Show all");
    container->addControl(button);

    button = new PPButton(BUTTON_SAMPLE_APPLY_LASTFILTER, screen, this, PPPoint(x2 + 2 + size + 1, y2 + 2 + bHeight * 2), PPSize(size, bHeightm + 1));
    button->setText("Redo filter");
    container->addControl(button);

    containerEntire->addControl(container);

    x2 += container->getSize().width;

    size = (conSize3 - 5);

    container = new PPContainer(CONTAINER_SAMPLE_EDIT1, screen, this, PPPoint(x2, y2), PPSize(conSize3, dHeight), false);
    container->setColor(TrackerConfig::colorThemeMain);

    button = new PPButton(BUTTON_SAMPLE_EDIT_CUT, screen, this, PPPoint(x2 + 2, y2 + 2), PPSize(size, bHeightm));
    button->setText("Cut");
    container->addControl(button);

    button = new PPButton(BUTTON_SAMPLE_EDIT_COPY, screen, this, PPPoint(x2 + 2, y2 + 2 + bHeight), PPSize(size, bHeightm));
    button->setText("Copy");
    container->addControl(button);

    button = new PPButton(BUTTON_SAMPLE_EDIT_PASTE, screen, this, PPPoint(x2 + 2, y2 + 2 + bHeight * 2), PPSize(size, bHeightm + 1));
    button->setText("Paste");
    container->addControl(button);

    containerEntire->addControl(container);

    x2 += container->getSize().width;

    size = (conSize4 - 5);

    container = new PPContainer(CONTAINER_SAMPLE_EDIT2, screen, this, PPPoint(x2, y2), PPSize(conSize4, dHeight), false);
    container->setColor(TrackerConfig::colorThemeMain);

    button = new PPButton(BUTTON_SAMPLE_EDIT_CROP, screen, this, PPPoint(x2 + 2, y2 + 2), PPSize(size, bHeightm));
    button->setText("Crop");
    container->addControl(button);

    button = new PPButton(BUTTON_SAMPLE_EDIT_VOL, screen, this, PPPoint(x2 + 2, y2 + 2 + bHeight), PPSize(size, bHeightm));
    button->setText("Vol");
    container->addControl(button);

    button = new PPButton(BUTTON_SAMPLE_EDIT_DRAW, screen, this, PPPoint(x2 + 2, y2 + 2 + bHeight * 2), PPSize(size, bHeightm + 1), true, true, false);
    button->setText("Draw");
    container->addControl(button);

    containerEntire->addControl(container);

    x2 += container->getSize().width;

    //y2+=container->getSize().height;

    container = new PPContainer(CONTAINER_SAMPLE_EDIT3, screen, this, PPPoint(x2, y2), PPSize(conSize5, 56), false);
    container->setColor(TrackerConfig::colorThemeMain);

    PPRadioGroup* radioGroup = new PPRadioGroup(RADIOGROUP_SAMPLE_LOOPTYPE, screen, this, PPPoint(x2 + 1, y2 - 2), PPSize(conSize5 - 1, 4 * 14));
    radioGroup->setColor(TrackerConfig::colorThemeMain);

    radioGroup->addItem("No loop");
    radioGroup->addItem("Forward");
    if (screen->getWidth() < 800)
        radioGroup->addItem("Bi-dir");
    else
        radioGroup->addItem("Ping-pong");
    radioGroup->addItem("One shot");

    container->addControl(radioGroup);

    containerEntire->addControl(container);

    // load container
    pp_int32 ty = y2;

    x2 += container->getSize().width;

    container = new PPContainer(CONTAINER_SAMPLE_EDIT4, screen, this, PPPoint(x2, ty), PPSize(conSize6, 27), false);
    container->setColor(TrackerConfig::colorThemeMain);

    radioGroup = new PPRadioGroup(RADIOGROUP_SAMPLE_RESTYPE, screen, this, PPPoint(x2 + 1, ty - 2), PPSize(conSize6 - 1, 28));
    radioGroup->setColor(TrackerConfig::colorThemeMain);

    radioGroup->addItem("8-bit");
    radioGroup->addItem("16-bit");

    container->addControl(radioGroup);

    containerEntire->addControl(container);

    ty += container->getSize().height;

    // ----------- load/save
    size = (conSize6 - 4) / 2 - 1;

    container = new PPContainer(CONTAINER_SAMPLE_LOADSAVE, screen, this, PPPoint(x2, ty), PPSize(conSize6, 29), false);
    container->setColor(TrackerConfig::colorThemeMain);

    button = new PPButton(BUTTON_SAMPLE_LOAD, screen, this, PPPoint(x2 + 2, ty + 2), PPSize(size, 12));
    button->setText("Load");
    container->addControl(button);

    size2 = (container->getLocation().x + container->getSize().width) - (x2 + 2 + size + 1) - 3;

    button = new PPButton(BUTTON_SAMPLE_SAVE, screen, this, PPPoint(x2 + 2 + size + 1, ty + 2), PPSize(size2, 12));
    button->setText("Save");
    container->addControl(button);

    // ----------- exit
    pp_int32 y3 = ty + 13;

    button = new PPButton(BUTTON_SAMPLEEDITOR_EXIT, screen, &tracker, PPPoint(x2 + 2, y3 + 2), PPSize(conSize6 - 5, 12));
    button->setText("Exit");
    container->addControl(button);

    containerEntire->addControl(container);

    x2 += container->getSize().width;

    conSize7 = screen->getWidth() - x2;

    container = new PPContainer(CONTAINER_SAMPLE_EDIT5, screen, this, PPPoint(x2, y2), PPSize(conSize7, 56), false);
    container->setColor(TrackerConfig::colorThemeMain);

    container->addControl(new PPStaticText(STATICTEXT_DISPLAY, NULL, NULL, PPPoint(x2 + 2 + 2, y2 + 4), screen->getWidth() < 800 ? "Displ." : "Display", true));
    container->addControl(new PPStaticText(STATICTEXT_LENGTH, NULL, NULL, PPPoint(x2 + 2 + 2, y2 + 4 + 13), "Length", true));
    container->addControl(new PPStaticText(STATICTEXT_REPSTART, screen, this, PPPoint(x2 + 2 + 2, y2 + 4 + 13 * 2), "Repeat", true));
    container->addControl(new PPStaticText(STATICTEXT_REPLEN, screen, this, PPPoint(x2 + 2 + 2, y2 + 4 + 13 * 3), "Replen.", true));

    x2 = screen->getWidth() - 43 - 3 - 4 - 8 * 8;

    container->addControl(new PPStaticText(STATICTEXT_SAMPLE_DISPLAY, screen, this, PPPoint(x2, y2 + 4), "12345678", false));
    container->addControl(new PPStaticText(STATICTEXT_SAMPLE_LENGTH, screen, this, PPPoint(x2, y2 + 4 + 13), "12345678", false));
    container->addControl(new PPStaticText(STATICTEXT_SAMPLE_REPSTART, screen, this, PPPoint(x2, y2 + 4 + 13 * 2), "12345678", false));
    container->addControl(new PPStaticText(STATICTEXT_SAMPLE_REPLENGTH, screen, this, PPPoint(x2, y2 + 4 + 13 * 3), "12345678", false));

    x2 = screen->getWidth() - 43 - 3;

    button = new PPButton(BUTTON_SAMPLE_EDIT_CLEAR, screen, this, PPPoint(x2, y2 + 2), PPSize(43, 12));
    button->setText("Clear");
    container->addControl(button);

    button = new PPButton(BUTTON_SAMPLE_EDIT_MINIMIZE, screen, this, PPPoint(x2, y2 + 2 + 13), PPSize(29, 12));
    button->setText("Min");
    container->addControl(button);

    button = new PPButton(BUTTON_FLIPNUMBERFORMAT, screen, this, PPPoint(x2 + 30, y2 + 2 + 13), PPSize(13, 12));
    button->setColor(TrackerConfig::colorThemeMain);
    button->setTextColor(PPUIConfig::getInstance()->getColor(PPUIConfig::ColorStaticText));
    button->setText("H");
    container->addControl(button);

    button = new PPButton(BUTTON_SAMPLE_EDIT_REPSTARTPLUS, screen, this, PPPoint(x2, y2 + 2 + 13 * 2), PPSize(14, 12));
    button->setText(TrackerConfig::stringButtonPlus);
    container->addControl(button);

    button = new PPButton(BUTTON_SAMPLE_EDIT_REPSTARTMINUS, screen, this, PPPoint(x2 + 15, y2 + 2 + 13 * 2), PPSize(14, 12));
    button->setText(TrackerConfig::stringButtonMinus);
    container->addControl(button);

    button = new PPButton(BUTTON_SAMPLE_EDIT_REPLENPLUS, screen, this, PPPoint(x2, y2 + 2 + 13 * 3), PPSize(14, 12));
    button->setText(TrackerConfig::stringButtonPlus);
    container->addControl(button);

    button = new PPButton(BUTTON_SAMPLE_EDIT_REPLENMINUS, screen, this, PPPoint(x2 + 15, y2 + 2 + 13 * 3), PPSize(14, 12));
    button->setText(TrackerConfig::stringButtonMinus);
    container->addControl(button);

    button = new PPButton(BUTTON_SHOWRANGE, screen, this, PPPoint(x2 + 15 + 15, y2 + 2 + 13 * 2), PPSize(13, 12 * 2 + 1));
    button->setColor(TrackerConfig::colorThemeMain);
    button->setTextColor(PPUIConfig::getInstance()->getColor(PPUIConfig::ColorStaticText));
    button->setFont(PPFont::getFont(PPFont::FONT_TINY));
    button->setText("Rng");
    button->setVerticalText(true);
    container->addControl(button);

    containerEntire->addControl(container);
    #else
    // sample editor
    PPContainer* sampleEditorContainer = new PPContainer(CONTAINER_SAMPLEEDITOR, screen, this, PPPoint(x, y), PPSize(320, 92), false);
    sampleEditorContainer->setColor(TrackerConfig::colorThemeMain);

    sampleEditorControl = new SampleEditorControl(SAMPLE_EDITOR, screen, this, PPPoint(x + 2, y + 2), PPSize(316, 92 - 4));
    sampleEditorControl->attachSampleEditor(tracker.moduleEditor->getSampleEditor());
    sampleEditorControl->setBorderColor(TrackerConfig::colorThemeMain);

    sampleEditorContainer->addControl(sampleEditorControl);
    containerEntire->addControl(sampleEditorContainer);

    pp_int32 x2 = x;
    pp_int32 y2 = sampleEditorContainer->getSize().height + y;

    PPContainer* container = new PPContainer(CONTAINER_SAMPLE_PLAY, screen, this, PPPoint(x2, y2), PPSize(87, 12 * 3 + 4), false);
    container->setColor(TrackerConfig::colorThemeMain);

    container->addControl(new PPStaticText(0, NULL, NULL, PPPoint(x2 + 4, y2 + 2), "Play:", true));
    container->addControl(new PPStaticText(STATICTEXT_SAMPLE_PLAYNOTE, screen, this, PPPoint(x2 + 8, y2 + 2 + 14), "C-5", false));

    PPButton* button = new PPButton(BUTTON_SAMPLE_PLAY_UP, screen, this, PPPoint(x2 + 38, y2 + 2 + 12), PPSize(18, 11));
    button->setText("Up");
    container->addControl(button);

    button = new PPButton(BUTTON_SAMPLE_PLAY_DOWN, screen, this, PPPoint(x2 + 38, y2 + 2 + 24), PPSize(18, 11));
    button->setText("Dn");
    container->addControl(button);

    button = new PPButton(BUTTON_SAMPLE_PLAY_STOP, screen, this, PPPoint(x2 + 2, y2 + 2 + 24), PPSize(34, 11));
    button->setText("Stop");
    container->addControl(button);

    button = new PPButton(BUTTON_SAMPLE_PLAY_WAVE, screen, this, PPPoint(x2 + 2 + 56, y2 + 2), PPSize(26, 11));
    button->setText("Wav");
    container->addControl(button);

    button = new PPButton(BUTTON_SAMPLE_PLAY_RANGE, screen, this, PPPoint(x2 + 2 + 56, y2 + 2 + 12), PPSize(26, 11));
    button->setText("Rng");
    container->addControl(button);

    button = new PPButton(BUTTON_SAMPLE_PLAY_DISPLAY, screen, this, PPPoint(x2 + 2 + 56, y2 + 2 + 12 * 2), PPSize(26, 11));
    button->setText("Dsp");
    container->addControl(button);

    containerEntire->addControl(container);

    x2 += container->getSize().width;
    container = new PPContainer(CONTAINER_SAMPLE_RANGE, screen, this, PPPoint(x2, y2), PPSize(66 * 2 + 6, 12 * 3 + 4), false);
    container->setColor(TrackerConfig::colorThemeMain);

    button = new PPButton(BUTTON_SAMPLE_RANGE_SHOW, screen, this, PPPoint(x2 + 2, y2 + 2), PPSize(66, 11));
    button->setText("Show rng");
    container->addControl(button);

    button = new PPButton(BUTTON_SAMPLE_RANGE_ALL, screen, this, PPPoint(x2 + 2, y2 + 2 + 12), PPSize(66, 11));
    button->setText("Rng all");
    container->addControl(button);

    button = new PPButton(BUTTON_SAMPLE_UNDO, screen, this, PPPoint(x2 + 2, y2 + 2 + 12 * 2), PPSize(32, 11));
    button->setText("Undo");
    button->setFont(PPFont::getFont(PPFont::FONT_TINY));
    container->addControl(button);

    button = new PPButton(BUTTON_SAMPLE_REDO, screen, this, PPPoint(x2 + 2 + 33, y2 + 2 + 12 * 2), PPSize(33, 11));
    button->setText("Redo");
    button->setFont(PPFont::getFont(PPFont::FONT_TINY));
    container->addControl(button);

    button = new PPButton(BUTTON_SAMPLE_RANGE_ZOOMOUT, screen, this, PPPoint(x2 + 2 + 67, y2 + 2), PPSize(66, 11));
    button->setText("Zoom out");
    container->addControl(button);

    button = new PPButton(BUTTON_SAMPLE_RANGE_SHOWALL, screen, this, PPPoint(x2 + 2 + 67, y2 + 2 + 12), PPSize(66, 11));
    button->setText("Show all");
    container->addControl(button);

    button = new PPButton(BUTTON_SAMPLE_APPLY_LASTFILTER, screen, this, PPPoint(x2 + 2 + 67, y2 + 2 + 12 * 2), PPSize(66, 11));
    button->setFont(PPFont::getFont(PPFont::FONT_TINY));
    button->setText("Redo filter");
    container->addControl(button);

    containerEntire->addControl(container);

    x2 += container->getSize().width;

    container = new PPContainer(CONTAINER_SAMPLE_EDIT1, screen, this, PPPoint(x2, y2), PPSize(47, 12 * 3 + 4), false);
    container->setColor(TrackerConfig::colorThemeMain);

    button = new PPButton(BUTTON_SAMPLE_EDIT_CUT, screen, this, PPPoint(x2 + 2, y2 + 2), PPSize(42, 11));
    button->setText("Cut");
    container->addControl(button);

    button = new PPButton(BUTTON_SAMPLE_EDIT_COPY, screen, this, PPPoint(x2 + 2, y2 + 2 + 12), PPSize(42, 11));
    button->setText("Copy");
    container->addControl(button);

    button = new PPButton(BUTTON_SAMPLE_EDIT_PASTE, screen, this, PPPoint(x2 + 2, y2 + 2 + 12 * 2), PPSize(42, 11));
    button->setText("Paste");
    container->addControl(button);

    containerEntire->addControl(container);

    x2 += container->getSize().width;

    container = new PPContainer(CONTAINER_SAMPLE_EDIT2, screen, this, PPPoint(x2, y2), PPSize(48, 12 * 3 + 4), false);
    container->setColor(TrackerConfig::colorThemeMain);

    button = new PPButton(BUTTON_SAMPLE_EDIT_CROP, screen, this, PPPoint(x2 + 2, y2 + 2), PPSize(43, 11));
    button->setText("Crop");
    container->addControl(button);

    button = new PPButton(BUTTON_SAMPLE_EDIT_VOL, screen, this, PPPoint(x2 + 2, y2 + 2 + 12), PPSize(43, 11));
    button->setText("Vol");
    container->addControl(button);

    button = new PPButton(BUTTON_SAMPLE_EDIT_DRAW, screen, this, PPPoint(x2 + 2, y2 + 2 + 12 * 2), PPSize(43, 11), true, true, false);
    button->setText("Draw");
    container->addControl(button);

    containerEntire->addControl(container);

    x2 = x;

    y2 += container->getSize().height;

    container = new PPContainer(CONTAINER_SHOWCONTEXTMENU, screen, this, PPPoint(x2, y2), PPSize(17, 52), false);
    container->setColor(TrackerConfig::colorThemeMain);

    button = new PPButton(BUTTON_SHOWCONTEXTMENU, screen, this, PPPoint(x2 + 2, y2 + 2), PPSize(12, container->getSize().height - 5));
    button->setVerticalText(true);
    button->setText("Menu");
    container->addControl(button);

    containerEntire->addControl(container);

    x2 += container->getSize().width;

    container = new PPContainer(CONTAINER_SAMPLE_EDIT3, screen, this, PPPoint(x2, y2), PPSize(65, 52), false);
    container->setColor(TrackerConfig::colorThemeMain);

    PPRadioGroup* radioGroup = new PPRadioGroup(RADIOGROUP_SAMPLE_LOOPTYPE, screen, this, PPPoint(x2 + 3, y2 + 1), PPSize(65, 50));
    radioGroup->setColor(TrackerConfig::colorThemeMain);
    radioGroup->setFont(PPFont::getFont(PPFont::FONT_TINY));

    radioGroup->addItem("No loop");
    radioGroup->addItem("Forward");
    radioGroup->addItem("Ping-pong");
    radioGroup->addItem("One shot");

    container->addControl(radioGroup);

    containerEntire->addControl(container);

    x2 += container->getSize().width;

    container = new PPContainer(CONTAINER_SAMPLE_EDIT4, screen, this, PPPoint(x2, y2), PPSize(66 - 16, 25), false);
    container->setColor(TrackerConfig::colorThemeMain);

    radioGroup = new PPRadioGroup(RADIOGROUP_SAMPLE_RESTYPE, screen, this, PPPoint(x2 + 1, y2 - 1), PPSize(65 - 16, 25));
    radioGroup->setColor(TrackerConfig::colorThemeMain);
    radioGroup->setFont(PPFont::getFont(PPFont::FONT_TINY));

    radioGroup->addItem("8-bit");
    radioGroup->addItem("16-bit");

    container->addControl(radioGroup);

    containerEntire->addControl(container);

    // Zoom container
    container = new PPContainer(CONTAINER_SAMPLE_ZOOMIN, screen, this, PPPoint(x2 + container->getSize().width, y2), PPSize(16, 25), false);
    container->setColor(TrackerConfig::colorThemeMain);

    button = new PPButton(BUTTON_SAMPLE_ZOOM_PLUS, screen, this, PPPoint(container->getLocation().x + 2, y2 + 2), PPSize(11, 10));
    button->setText("+");
    container->addControl(button);

    button = new PPButton(BUTTON_SAMPLE_ZOOM_MINUS, screen, this, PPPoint(button->getLocation().x, y2 + 2 + button->getSize().height + 1), PPSize(11, 9));
    button->setText("-");
    container->addControl(button);

    containerEntire->addControl(container);

    pp_int32 y3 = y2 + container->getSize().height;

    container = new PPContainer(CONTAINER_SAMPLE_LOADSAVE, screen, this, PPPoint(x2, y3), PPSize(66, 27), false);
    container->setColor(TrackerConfig::colorThemeMain);

    button = new PPButton(MAINMENU_INSEDIT, screen, &tracker, PPPoint(x2 + 2, y3 + 2 + 12), PPSize(34, 10));
    button->setFont(PPFont::getFont(PPFont::FONT_TINY));
    button->setText("Ins.Ed.");
    container->addControl(button);

    button = new PPButton(BUTTON_SAMPLEEDITOR_EXIT, screen, &tracker, PPPoint(x2 + 2 + 35, y3 + 2 + 12), PPSize(26, 10));
    button->setFont(PPFont::getFont(PPFont::FONT_TINY));
    button->setText("Exit");
    container->addControl(button);

    button = new PPButton(BUTTON_SAMPLE_LOAD, screen, this, PPPoint(x2 + 2, y3 + 2), PPSize(30, 11));
    button->setFont(PPFont::getFont(PPFont::FONT_TINY));
    button->setText("Load");
    container->addControl(button);

    button = new PPButton(BUTTON_SAMPLE_SAVE, screen, this, PPPoint(x2 + 2 + 31, y3 + 2), PPSize(30, 11));
    button->setFont(PPFont::getFont(PPFont::FONT_TINY));
    button->setText("Save");
    container->addControl(button);

    containerEntire->addControl(container);

    x2 += container->getSize().width;

    container = new PPContainer(CONTAINER_SAMPLE_EDIT5, screen, this, PPPoint(x2, y2), PPSize(172, 52), false);
    container->setColor(TrackerConfig::colorThemeMain);

    container->addControl(new PPStaticText(STATICTEXT_DISPLAY, NULL, NULL, PPPoint(x2 + 2, y2 + 4), "Display", true));
    container->addControl(new PPStaticText(STATICTEXT_LENGTH, NULL, NULL, PPPoint(x2 + 2, y2 + 4 + 12), "Length", true));
    container->addControl(new PPStaticText(STATICTEXT_REPSTART, screen, this, PPPoint(x2 + 2, y2 + 4 + 12 * 2), "Repeat", true));
    container->addControl(new PPStaticText(STATICTEXT_REPLEN, screen, this, PPPoint(x2 + 2, y2 + 4 + 12 * 3), "Replen.", true));

    container->addControl(new PPStaticText(STATICTEXT_SAMPLE_DISPLAY, screen, this, PPPoint(x2 + 2 + 58, y2 + 4), "12345678", false));
    container->addControl(new PPStaticText(STATICTEXT_SAMPLE_LENGTH, screen, this, PPPoint(x2 + 2 + 58, y2 + 4 + 12), "12345678", false));
    container->addControl(new PPStaticText(STATICTEXT_SAMPLE_REPSTART, screen, this, PPPoint(x2 + 2 + 58, y2 + 4 + 12 * 2), "12345678", false));
    container->addControl(new PPStaticText(STATICTEXT_SAMPLE_REPLENGTH, screen, this, PPPoint(x2 + 2 + 58, y2 + 4 + 12 * 3), "12345678", false));

    button = new PPButton(BUTTON_SAMPLE_EDIT_CLEAR, screen, this, PPPoint(x2 + 126, y2 + 2), PPSize(43, 11));
    button->setText("Clear");
    container->addControl(button);

    button = new PPButton(BUTTON_SAMPLE_EDIT_MINIMIZE, screen, this, PPPoint(x2 + 126, y2 + 2 + 12), PPSize(27, 11));
    button->setText("Min");
    container->addControl(button);

    button = new PPButton(BUTTON_FLIPNUMBERFORMAT, screen, this, PPPoint(x2 + 126 + 28, y2 + 2 + 12), PPSize(15, 11));
    button->setColor(TrackerConfig::colorThemeMain);
    button->setTextColor(PPUIConfig::getInstance()->getColor(PPUIConfig::ColorStaticText));
    button->setText("H");
    container->addControl(button);

    button = new PPButton(BUTTON_SAMPLE_EDIT_REPSTARTPLUS, screen, this, PPPoint(x2 + 126, y2 + 2 + 12 * 2), PPSize(13, 11));
    button->setText(TrackerConfig::stringButtonPlus);
    container->addControl(button);

    button = new PPButton(BUTTON_SAMPLE_EDIT_REPSTARTMINUS, screen, this, PPPoint(x2 + 126 + 14, y2 + 2 + 12 * 2), PPSize(13, 11));
    button->setText(TrackerConfig::stringButtonMinus);
    container->addControl(button);

    button = new PPButton(BUTTON_SAMPLE_EDIT_REPLENPLUS, screen, this, PPPoint(x2 + 126, y2 + 2 + 12 * 3), PPSize(13, 11));
    button->setText(TrackerConfig::stringButtonPlus);
    container->addControl(button);

    button = new PPButton(BUTTON_SAMPLE_EDIT_REPLENMINUS, screen, this, PPPoint(x2 + 126 + 14, y2 + 2 + 12 * 3), PPSize(13, 11));
    button->setText(TrackerConfig::stringButtonMinus);
    container->addControl(button);

    button = new PPButton(BUTTON_SHOWRANGE, screen, this, PPPoint(x2 + 126 + 14 * 2, y2 + 2 + 12 * 2), PPSize(15, 11 * 2 + 1));
    button->setColor(TrackerConfig::colorThemeMain);
    button->setTextColor(PPUIConfig::getInstance()->getColor(PPUIConfig::ColorStaticText));
    button->setFont(PPFont::getFont(PPFont::FONT_TINY));
    button->setText("Rng");
    button->setVerticalText(true);
    container->addControl(button);

    containerEntire->addControl(container);
    #endif
    containerEntire->adjustContainerSize();
    screen->addControl(containerEntire);

    initialised = true;

    showSection(false);
}

void SectionSamples::showSection(bool bShow)
{
    containerEntire->show(bShow);
}

void SectionSamples::realign()
{
    pp_uint32 maxShould = tracker.MAXEDITORHEIGHT();
    pp_uint32 maxIs = containerEntire->getLocation().y + containerEntire->getSize().height;

    if (maxIs != maxShould)
    {
        pp_int32 offset = maxShould - maxIs;
        containerEntire->move(PPPoint(0, offset));
    }

    PatternEditorControl* control = tracker.getPatternEditorControl();
    PPScreen* screen = tracker.screen;

    if (visible)
    {
        control->setSize(PPSize(screen->getWidth(),
                                tracker.MAXEDITORHEIGHT() - tracker.SAMPLESECTIONDEFAULTHEIGHT() - tracker.UPPERSECTIONDEFAULTHEIGHT() + 1));
    }
    else
    {
        control->setSize(PPSize(screen->getWidth(), tracker.MAXEDITORHEIGHT() - tracker.UPPERSECTIONDEFAULTHEIGHT()));
    }
}

void SectionSamples::show(bool bShow)
{
    #ifdef __LOWRES__
    PPScreen* screen = tracker.screen;
    screen->pauseUpdate(true);
    #endif
    SectionAbstract::show(bShow);

    visible = bShow;

    if (!initialised)
    {
        init();
    }

    if (initialised)
    {
        PatternEditorControl* control = tracker.getPatternEditorControl();

        #ifndef __LOWRES__
        realign();
        #endif

        if (bShow)
        {
            if (control)
            {
                #ifdef __LOWRES__
                control->show(false);
                replaceInstrumentListBoxes(true, 56);
                #endif
            }
            tracker.hideInputControl();
        }
        else if (control)
        {
            #ifdef __LOWRES__
            control->show(true);
            replaceInstrumentListBoxes(false);
            #endif
        }

        update();
        showSection(bShow);
    }

    #ifdef __LOWRES__
    // If instrument section is shown (bShow = true)
    // set focus to the Instrumentlist container (instrument listbox)
    // but before disable screen updates to prevent flickering
    if (bShow)
    {
        screen->setFocus(screen->getControlByID(CONTAINER_INSTRUMENTLIST));
    }
    screen->pauseUpdate(false);
    if (!bShow)
    {
        screen->update();
    }
    #endif
}

void SectionSamples::update(bool repaint /* = true*/)
{
    realUpdate(repaint, false, true);
}

void SectionSamples::notifyTabSwitch()
{
    if (isVisible())
        realign();
}

// No need to reattach sample again, because reattaching also clears out selection
void SectionSamples::refresh(bool repaint /* = true*/)
{
    realUpdate(repaint, false, false);
}

void SectionSamples::realUpdate(bool repaint, bool force, bool reAttach)
{
    if (!initialised)
        return;

    PPScreen* screen = tracker.screen;
    SampleEditor* sampleEditor = sampleEditorControl->getSampleEditor();

    if (!force && screen->getModalControl() && screen->getModalControl() == tracker.messageBoxContainerGeneric)
        return;

    if (reAttach)
        tracker.moduleEditor->reloadSample(tracker.listBoxInstruments->getSelectedIndex(), tracker.listBoxSamples->getSelectedIndex());

    if (!visible)
        return;

    PPContainer* container = static_cast<PPContainer*>(screen->getControlByID(CONTAINER_SAMPLE_EDIT3));

    sampleEditorControl->setRelativeNote(currentSamplePlayNote - ModuleEditor::MAX_NOTE / 2);

    static_cast<PPRadioGroup*>(container->getControlByID(RADIOGROUP_SAMPLE_LOOPTYPE))->setChoice(sampleEditor->getLoopType() & 3);

    PPContainer* container2 = static_cast<PPContainer*>(screen->getControlByID(CONTAINER_SAMPLE_EDIT4));
    static_cast<PPRadioGroup*>(container2->getControlByID(RADIOGROUP_SAMPLE_RESTYPE))->setChoice(sampleEditor->is16Bit() ? 1 : 0);

    PPContainer* container3 = static_cast<PPContainer*>(screen->getControlByID(CONTAINER_SAMPLE_EDIT5));

    setOffsetText(STATICTEXT_SAMPLE_LENGTH, sampleEditor->getSampleLen());
    setOffsetText(STATICTEXT_SAMPLE_DISPLAY, sampleEditorControl->getCurrentDisplayRange());

    static const char offsetTypes[3] = { 'H', 'D', 'T' };

    static_cast<PPButton*>(container3->getControlByID(BUTTON_FLIPNUMBERFORMAT))->setText(offsetTypes[offsetFormat]);

    if (showRangeOffsets)
    {
        static_cast<PPButton*>(container3->getControlByID(BUTTON_SHOWRANGE))->setText("Rng");
        static_cast<PPStaticText*>(container3->getControlByID(STATICTEXT_REPSTART))->setText("RStart");
        static_cast<PPStaticText*>(container3->getControlByID(STATICTEXT_REPLEN))->setText("REnd");
        pp_int32 sStart = sampleEditorControl->getSelectionStart();
        pp_int32 sEnd = sampleEditorControl->getSelectionEnd();
        if (sStart >= 0 && sEnd >= 0)
        {
            setOffsetText(STATICTEXT_SAMPLE_REPSTART, sStart);
            setOffsetText(STATICTEXT_SAMPLE_REPLENGTH, sEnd);
        }
        else
        {
            static_cast<PPStaticText*>(container3->getControlByID(STATICTEXT_SAMPLE_REPSTART))->setText("--------");
            static_cast<PPStaticText*>(container3->getControlByID(STATICTEXT_SAMPLE_REPLENGTH))->setText("--------");
        }
    }
    else
    {
        static_cast<PPButton*>(container3->getControlByID(BUTTON_SHOWRANGE))->setText("Rep");
        static_cast<PPStaticText*>(container3->getControlByID(STATICTEXT_REPSTART))->setText("Repeat");
        static_cast<PPStaticText*>(container3->getControlByID(STATICTEXT_REPLEN))->setText("Replen.");

        setOffsetText(STATICTEXT_SAMPLE_REPSTART, sampleEditorControl->getRepeatStart());
        setOffsetText(STATICTEXT_SAMPLE_REPLENGTH, sampleEditorControl->getRepeatLength());
    }

    PPContainer* container4 = static_cast<PPContainer*>(screen->getControlByID(CONTAINER_SAMPLE_PLAY));
    char noteName[4];
    PatternTools::getNoteName(noteName, currentSamplePlayNote + 1);
    static_cast<PPStaticText*>(container4->getControlByID(STATICTEXT_SAMPLE_PLAYNOTE))->setText(noteName);

    PPContainer* container5 = static_cast<PPContainer*>(screen->getControlByID(CONTAINER_SAMPLE_RANGE));
    static_cast<PPButton*>(container5->getControlByID(BUTTON_SAMPLE_RANGE_ALL))->setClickable(!sampleEditor->isEmptySample());
    static_cast<PPButton*>(container5->getControlByID(BUTTON_SAMPLE_RANGE_SHOWALL))->setClickable(!sampleEditor->isEmptySample());
    static_cast<PPButton*>(container5->getControlByID(BUTTON_SAMPLE_RANGE_ZOOMOUT))->setClickable(sampleEditorControl->canZoomOut());
    static_cast<PPButton*>(container5->getControlByID(BUTTON_SAMPLE_RANGE_SHOW))->setClickable(sampleEditorControl->hasValidSelection());
    static_cast<PPButton*>(container5->getControlByID(BUTTON_SAMPLE_APPLY_LASTFILTER))->setClickable(sampleEditor->tool_canApplyLastFilter());
    static_cast<PPButton*>(container5->getControlByID(BUTTON_SAMPLE_UNDO))->setClickable(sampleEditor->canUndo());
    static_cast<PPButton*>(container5->getControlByID(BUTTON_SAMPLE_REDO))->setClickable(sampleEditor->canRedo());

    PPContainer* container6 = static_cast<PPContainer*>(screen->getControlByID(CONTAINER_SAMPLE_EDIT2));
    static_cast<PPButton*>(container6->getControlByID(BUTTON_SAMPLE_EDIT_CROP))->setClickable(sampleEditorControl->hasValidSelection());
    static_cast<PPButton*>(container6->getControlByID(BUTTON_SAMPLE_EDIT_VOL))->setClickable(!sampleEditor->isEmptySample());
    static_cast<PPButton*>(container6->getControlByID(BUTTON_SAMPLE_EDIT_DRAW))->setClickable(!sampleEditor->isEmptySample());

    PPContainer* container7 = static_cast<PPContainer*>(screen->getControlByID(CONTAINER_SAMPLE_PLAY));
    static_cast<PPButton*>(container7->getControlByID(BUTTON_SAMPLE_PLAY_RANGE))->setClickable(sampleEditorControl->hasValidSelection());
    static_cast<PPButton*>(container7->getControlByID(BUTTON_SAMPLE_PLAY_WAVE))->setClickable(!sampleEditor->isEmptySample());
    static_cast<PPButton*>(container7->getControlByID(BUTTON_SAMPLE_PLAY_DISPLAY))->setClickable(!sampleEditor->isEmptySample());

    PPContainer* container9 = static_cast<PPContainer*>(screen->getControlByID(CONTAINER_SAMPLE_EDIT1));
    bool b = (sampleEditorControl->getCurrentRangeLength()) > 0 && sampleEditorControl->hasValidSelection();
    static_cast<PPButton*>(container9->getControlByID(BUTTON_SAMPLE_EDIT_CUT))->setClickable(b);
    static_cast<PPButton*>(container9->getControlByID(BUTTON_SAMPLE_EDIT_COPY))->setClickable(b);
    static_cast<PPButton*>(container9->getControlByID(BUTTON_SAMPLE_EDIT_PASTE))->setClickable(sampleEditor->canPaste());

    PPContainer* container10 = static_cast<PPContainer*>(screen->getControlByID(CONTAINER_SAMPLE_LOADSAVE));
    static_cast<PPButton*>(container10->getControlByID(BUTTON_SAMPLE_SAVE))->setClickable(!sampleEditor->isEmptySample());

    screen->paintControl(container10, false);
    screen->paintControl(container9, false);
    screen->paintControl(container6, false);
    screen->paintControl(container5, false);
    screen->paintControl(container4, false);
    screen->paintControl(container, false);
    screen->paintControl(container2, false);
    screen->paintControl(container3, false);
    screen->paintControl(sampleEditorControl, false);
    if (repaint)
        screen->update();
}

void SectionSamples::updateSampleWindow(bool repaint /* = true*/)
{
    PPScreen* screen = tracker.screen;
    screen->paintControl(sampleEditorControl, false);
    if (repaint)
        screen->update();
}

void SectionSamples::updateAfterLoad()
{
    tracker.updateInstrumentsListBox(false);
    tracker.updateSamplesListBox(false);
    tracker.sectionInstruments->update(false);
    update(false);
}

SampleEditorControl* SectionSamples::getSampleEditorControl(bool forceAttach /* = true*/)
{
    if (forceAttach &&
        sampleEditorControl &&
        sampleEditorControl->getSampleEditor()->getSample() == NULL)
    {
        tracker.moduleEditor->reloadSample(tracker.listBoxInstruments->getSelectedIndex(), tracker.listBoxSamples->getSelectedIndex());
    }

    return sampleEditorControl;
}

void SectionSamples::resetSampleEditor()
{
    if (sampleEditorControl)
        sampleEditorControl->reset();
}

bool SectionSamples::isEmptySample()
{
    return !tracker.getSampleEditor()->isEditableSample();
}

void SectionSamples::setOffsetFormat(pp_uint32 offsetFormat)
{
    this->offsetFormat = offsetFormat;

    sampleEditorControl->setOffsetFormat((SampleEditorControl::OffsetFormats)offsetFormat);
}

void SectionSamples::toggleOffsetFormat()
{
    offsetFormat = (offsetFormat + 1) % (SampleEditorControl::OffsetFormatMillis + 1);

    sampleEditorControl->setOffsetFormat((SampleEditorControl::OffsetFormats)offsetFormat);
}

void SectionSamples::setOffsetText(pp_uint32 ID, pp_uint32 offset)
{
    switch (offsetFormat)
    {
        case SampleEditorControl::OffsetFormatDec:
            static_cast<PPStaticText*>(containerEntire->getControlByID(ID))->setValue(offset, false, 8);
            break;

        case SampleEditorControl::OffsetFormatHex:
            static_cast<PPStaticText*>(containerEntire->getControlByID(ID))->setValue(offset, true, 8);
            break;

        case SampleEditorControl::OffsetFormatMillis:
        {
            pp_uint32 millis = sampleEditorControl->getSampleEditor()->convertSmpPosToMillis(offset, currentSamplePlayNote - ModuleEditor::MAX_NOTE / 2);
            char buffer[32], buffer2[32];
            memset(buffer2, 32, sizeof(buffer2));
            // we only have 7 digits, one period character is contained too
            SampleEditorControl::formatMillis(buffer, millis % 10000000);
            // string too large
            if (strlen(buffer) > 8)
            {
                // try to cut off msecs (from period)
                char* ptr = buffer + strlen(buffer);
                while (*ptr != '.' && ptr > buffer)
                    ptr--;
                if (*ptr == '.')
                {
                    *ptr++ = 's';
                    *ptr = '\0';
                }
                // string still too large?
                if (strlen(buffer) > 8)
                {
                    // cut off minutes part (from m)
                    char* ptr = buffer + strlen(buffer);
                    while (*ptr != 'm' && ptr > buffer)
                        ptr--;
                    if (*ptr == 'm')
                        *(++ptr) = '\0';
                }
                if (strlen(buffer) > 8)
                    strcpy(buffer, "toolarge");
            }
            strcpy(buffer2 + (8 - strlen(buffer)), buffer);
            static_cast<PPStaticText*>(containerEntire->getControlByID(ID))->setText(buffer2);
            break;
        }
    }
}

void SectionSamples::handleClearSample()
{
    SampleEditor* sampleEditor = sampleEditorControl->getSampleEditor();
    if (sampleEditor->isEditableSample())
    {
        if (sampleEditor->isUndoStackEnabled())
        {
            sampleEditor->clearSample();
        }
        else
        {
            showMessageBox(MESSAGEBOX_CLEARSAMPLE, "Clear sample?");
        }
    }
    else
    {
        update();
    }
}

void SectionSamples::handleCropSample()
{
    SampleEditor* sampleEditor = sampleEditorControl->getSampleEditor();
    if (sampleEditor->isEditableSample() && sampleEditorControl->hasValidSelection())
    {
        if (sampleEditor->isUndoStackEnabled())
        {
            sampleEditor->cropSample();
        }
        else
        {
            showMessageBox(MESSAGEBOX_CROPSAMPLE, "Crop sample?");
        }
    }
    else
    {
        update();
    }
}

void SectionSamples::handleMinimizeSample()
{
    SampleEditor* sampleEditor = sampleEditorControl->getSampleEditor();
    if (sampleEditor->canMinimize())
    {
        if (sampleEditor->isUndoStackEnabled())
        {
            sampleEditor->minimizeSample();
        }
        else
        {
            showMessageBox(MESSAGEBOX_MINIMIZESAMPLE, "Minimize sample?");
        }
    }
    else
    {
        update();
    }
}

void SectionSamples::handleConvertSampleResolution()
{
    SampleEditor* sampleEditor = sampleEditorControl->getSampleEditor();
    if (sampleEditor->isEditableSample())
    {
        showMessageBox(MESSAGEBOX_CONVERTSAMPLE, "Convert sample data?", true);
    }
    else
    {
        sampleEditor->convertSampleResolution(false);
        update();
    }
}